/**
 * 1. 对应名称和从属关系
 * 
 * 对应名称：
 * proptotype: 原型 
 * __proto__:   原型链（连接点）
 * 从属关系
 * prototype：函数的一个属性：对象 {}
 * __proto__:  对象Object的一个属性： 对象{}
 * 对象的__proto__保存着该对象构造函数的prototype
*/

//2.从属关系和原型链基本认知
function Text () {
  this.a = 1;
  this.b = 222;
}
// 函数只要声明出来，就有prototype属性，是一个对象
Text.prototype.b = 2;
console.log(Text.prototype);//{constructor: ƒ}
// new Text() 函数构造出一个对象的实例，
const text = new Text();
//对象的实例默认有__proto__属性（当然也可以创建__proto__为null的对象）
console.log(text.__proto__);//{constructor: ƒ}
//对象的__proto__保存着该对象构造函数的prototype，因此text.__proto__ === Text.prototype为true
console.log(text.__proto__ === Text.prototype); //true

// Test.prototype=>{__proto__} ,Test.prototype 对应了一个对象，那么这个对象默认有__proto__属性，每个对象都有
console.log(Text.prototype.__proto__); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
Text.prototype.c = 333;

// 函数的原型的__proto__属性是 Object.prototype，它是最顶层的原型，它的__proto___属性是null
console.log(Text.prototype.__proto__ === Object.prototype); //true;

console.log(Object.prototype.__proto__); // null

Object.prototype.c = 3;
//3.认识原型链，原型与原型链继承

console.log(text);

/**
 * 原型链： 以一个对象基准，原型为节点，__proto__为连接，一直连接到Object.prototype为止的链条叫做原型链。
 * 原型链继承：沿着__proto__找原型链上原型的属性，找到了就获取属性的值，找不到就继续向上查
 * test {
 *  a:1;
 *  a:222;
 *  __proto__: Test.prototype = {
 *    b:2;
 *    c:333;
 *    __proto__:Object.prototype = {
 *      c:3;
 *      x __proto__ 没有更上层的原型
 *    }
 *  }
 * }
 */
console.log(text.a);//1
console.log(text.b);//222
console.log(text.c);//333


//4.Function与Object的特殊性

// Function 和 Object ：既是 函数 也是 对象

//Text 函数底层是 new Function() 构造出来的(类似于 const Text = new Function() )，
//那么它本身也是对象，它也应该有__proto__属性,__proto__指向构造函数的prototype属性,也就是Fucntion.prototype
console.log(Text.__proto__ === Function.prototype);//true
console.log(Function.prototype === Object.prototype);//false
// 当然，Function是函数那么自然包含prototype属性，Function.prototype指向的是原型对象，必然包含__proto__属性，Function.prototype.__proto__指向Object.prototype
console.log(Function.prototype.__proto__ === Object.prototype);//true

// Function 本身也是函数,也应该包含__proto___和prototype,都由native 底层实现,它们是同一个对象。
// Function对象构建了它本身，这是个底层实现，
// console.log(Function);//ƒ Function() { [native code] }
console.log(Function.prototype);//ƒ { [native code] }
console.log(Function.__proto__);//ƒ { [native code] }
console.log(Function.__proto__ === Function.prototype); //true

//const obj = {};
//const obj = new Object();
// Object 本身也是函数，那么它的__proto__也应该指向 Function.prototype
console.log(typeof Object); //function
console.log(Object.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.__proto__);//true;



//5. 判断属性是否存在方法
//判断对象本身是否包含该属性
console.log("----------------------");
console.log(text.hasOwnProperty('a'));//true
console.log(text.hasOwnProperty('b'));//true
console.log(text.hasOwnProperty('c'));//false
//判断对象原型链上是否包含该属性
console.log("----------------------");
console.log('a' in text); //true
console.log('b' in text); //true
console.log('c' in text); //true

//6. 构造函数constructor 与实例直接的关系和特征
// text.constructor -> 实例化text对象的构造函数，它是可以更改的
console.log(text.constructor === Text); //true
function Text1  () {
  this.a = 111;
};
//constructor构造函数改为 Text1
text.constructor = Text1;
console.log(text);
/**Text {a: 1, b: 222, constructor: ƒ} 
 * a : 1 
 * b : 222 
 * constructor : ƒ Text1() */
